#define _CRT_SECURE_NO_WARNINGS
// ↑ 将本行在代码放在第一行可以避免 scanf的报错问题（仅在VS编译器里）
//【进阶篇】144.枚举
//【进阶篇】145.休息
//【进阶篇】146.联合
//【进阶篇】147.动态内存管理（1）
//【进阶篇】148.休息
//【进阶篇】149.动态内存管理（2）
//【进阶篇】150.视频分享课

#include<stdio.h>
#include<stdlib.h> //malloc
#include<string.h> //strerror
#include<errno.h>  //errno


int main()
{
	//144.枚举
	{
		enum Day
		{
			Mon,//0
			Tues,//1
			Wed,//2
			Thur,//3
			Fri,//4
			Sat,//5
			Sun=7//7
		};
		enum Day d = Fri;
		printf("%d\n", d);
		printf("%d\n", Sun);
	}

	//146.联合
	{
		union Un
		{
			int a;
			char c;
		};
		union Un u;
		printf("%d \n %p\n %p\n %p\n", sizeof(u), &u.a, &u.c, &u);

		union Un2
		{
			char arr[5];
			int a;
		};
		union Un2 u2;
		printf("%d\n", sizeof(u2));
	}

	//147.动态内存管理_动态内存函数 malloc:动态内存开辟 free:动态内存释放
	{
		int* p = (int*)malloc(40);
		if (p == NULL)
		{
			printf("%s\n", strerror(errno));
			return 1;
		}
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
		free(p);
		p = NULL;
		printf("\n");
	}
	//147.动态内存管理_动态内存函数 calloc:动态内存开辟(具备初始化)
	{
		int *p = (int*)calloc(10, 4);
		if (p == NULL)
		{
			printf("%s\n", strerror(errno));
			return 1;
		}
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
		free(p);
		p = NULL;
		printf("\n");
	}
	//147.动态内存管理_动态内存函数 realloc:动态内存调整
	{
		int* p = (int*)malloc(40);
		if (p == NULL)
		{
			printf("%s\n", strerror(errno));
			return 1;
		}
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		
		//realloc
		int*ptr =(int*)realloc(p, 80);//使得开辟空间从40 变为80
		if (ptr != NULL)
		{
			p = ptr;
			ptr = NULL;
		}
		for (; i < 20; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 20; i++)
		{
			printf("%d ", *(p + i));
		}
		free(p);
		p = NULL;
		printf("%p %p", p, ptr);//如果没有自行将ptr指向空指针，ptr会变为野指针，因为pir所指向的内存已被释放
		printf("\n");
	}






	return 0;
}
//144.枚举：一一列举
	// 枚举的格式：enum 名称{ 值，值，... ，值 }；
	// 枚举的优点：
		// 增加代码可读性和可维护性，便于调试，使用方便
		// 相较于#define 枚举类型检查更严谨
		// 防止命名污染（封装）
//146.联合-所有成员共用一块空间，可以在一定程度上节省空间，但是每次使用时只能使用一个成员，其他成员内存的值可能会随动
	// 格式：union 名称{ 成员类型 名称; 成员类型 名称; }
	// 大小计算：联合体也存在内存对齐，所以内存对齐要以最大对齐数为准
//147.动态内存管理
	// 动态内存函数：malloc calloc realloc free
	// malloc:动态内存开辟
		// 传参 1.开辟空间大小 
		// 开辟成功返回指向开辟空间的指针，开辟失败则返回NULL
		// malloc返回值是void* 泛指针，所以开辟空间的类型需要由使用者进行定义和规定 
		// malloc开辟的空间在堆区
		// 栈区用于存放局部变量、形式参数
	// free:释放动态内存空间
		// 传参 释放空间的起始地址
		// 在使用完动态内存空间后，利用free释放正确用法
		// free(p);释放空间   p = NULL;将指针指向空
		// 只能释放动态内存空间
	// calloc:动态内存开辟
		// 传参 1.开辟空间元素个数；2.每个元素所占空间大小
		// calloc在开辟空间时会对开辟空间进行初始化，全部置0
		// 可以理解为calloc = malloc + memset 
	//realloc:动态内存调整
		// 传参 1.调整内存空间的起始地址 2.调整内存空间的大小
		// 如果调整时原空间后足够则直接调整，
		// 如果不够则另找一块足够的空间，将原空间的值拷贝到新开空间内并释放原空间
		// realloc(NULL,size)则可以视为malloc 




